feat(skills): configurable SSOT storage location (cc-switch | unified), align with upstream GUI - #414
feat(skills): configurable SSOT storage location (cc-switch | unified), align with upstream GUI#414ShatterDusk wants to merge 8 commits into
Conversation
…creation, TUI/CLI error surfacing, clap alias, no-op hint P1-1: copy_dir_recursive failure now cleans partial dst; source cleanup failures logged P1-2: TUI storage-location toast shows errors/skipped count (Warning on failure) P1-3: extract ssot_dir_for(); migrate_storage uses create_managed_config_dir_all P2-1: clap value alias cc_switch for CcSwitch P2-3: CLI no-op early return; error path prints failures + backup hint test: migrate_storage_keeps_source_and_setting_on_failure
|
Thanks for the PR! 🙏 It is not ready to merge yet. Main blockers:
Formatting and the new targeted tests pass, but these migration issues should be fixed first. I recommend following the upstream backend behavior and keeping the TUI consistent with the existing confirmation/help patterns. 🙂 |
…app sync, symlink refresh, TUI confirm dialog, text clarity - migrate_storage now iterates DB-managed skills only (not unmanaged dirs) - post-migration sync respects each skill's enabled app matrix - destination-exists case still refreshes app symlinks to new SSOT - add require_valid_directory traversal guard - TUI: confirm dialog before migration (ConfirmAction::SkillsMigrateStorage) - TUI: rename label to 技能存储位置 / Skill storage location - test: migrate_storage_skips_unmanaged_dirs
|
Thanks for the detailed review — all four migration blockers are addressed in the latest commits ( 1. Migration now respects the configured app selection 2. Only DB-managed skills are migrated 3. Destination-exists case refreshes app symlinks 4. TUI confirmation before migration 5. Full test suite compilation errors Formatting and targeted tests pass; |
|
Added soap-opera tests for migrate_storage (commit ad19ec27) — four disaster scenes stacking extreme conditions: managed/unmanaged/hidden/traversal-DB-row + destination conflict + symlink repointing in one migration; pre-occupied backup dir; empty-DB migration; and a roundtrip that must not drag unmanaged dirs back. All pass (26/26 in services::skill). These are the scenarios your blockers pointed at, now locked in as regressions. |
|
Independent audit (mutation testing) of the test suite, then fixed what it found (commit c44d2dc3):
27/27 tests pass in services::skill. |
Summary
Add configurable skills SSOT storage location (
skill_storage_location:cc-switch|unified) to the CLI, aligning with the upstream GUI'sskillStorageLocationfeature (farion1231/cc-switch). Inunifiedmode,~/.agents/skills/becomes the SSOT — the cross-tool standard directory adopted by skills.sh, LangChain, and six major harnesses.Closes #413
Motivation
~/.agents/skills/is the de-facto cross-harness standard for agent skills (Codex, Gemini CLI, DSH, OpenCode, Windsurf, Warp scan it natively; LangChain deepagents and skills.sh adopt it). The CLI's SSOT was hardcoded to{config_dir}/skills, forcing users of the.agentsconvention into two divergent skill copies. See #413 for the full harness adoption matrix.Changes
src/services/skill.rsSkillStorageLocationenum;get_ssot_dir()honors location;migrate_storage()with pre-migration backup;validate_skill_storage_destination()src/settings.rsskill_storage_locationfield (#[serde(default)]), get/set functionssrc/lib.rssrc/cli/commands/skills.rsskills storage-locationcommand (get/set + triggers migration)tests/skills_service.rsCLI usage
Behavior (aligned with upstream GUI's migrate_storage)
{config_dir}/skill-backups/(new: upstream has no backup; added for rollback safety)Testing
migrate_storage_*,get_ssot_dir_switches_on_location) + 3 integration tests (storage_location_*) — all passservices::skillmodule: 20/20 passcli::tui::theme::tests(terminal color detection fails in non-TTY env), unrelated to this change (verified on clean baseline viagit stash)cargo fmt --checkclean;cargo clippyno new warningsNotes
cc-switch/unifiedfor CLI args; serde snake_casecc_switch/unifiedin settings.jsonmigrate_storagetraverses the SSOT directory (not the index), so traversal-safe by construction